[OpenBSD] OpenSSH jako serwer SFTP czyli bezpieczny serwer plików
Kategoria: FAQ, etykiety: openbsd, openssh, sftp, serwer plików
Dodany: 2016-08-04 22:58
(zmodyfikowany: 2016-09-25 16:16)
Przez: uzytkownikubunt
Wyświetleń: 17471
Wersja oprogramowania
Poradnik pisany wobec serwera OpenSSH, w wersji 7.3, uruchomionego w rozwojowej wersji systemu OpenBSD-current (sierpień 2016).
Co przedstawia poradnik
Poradnik pokazuje jak dla dwóch określonych użytkowników (Andrzej, Magda, a w zasadzie odpowiednio: _ssh_andrzej, _ssh_magda), których rozróżnimy za pomocą używanych przez nich kluczy, pozwolić na dostęp do serwera plików SFTP (zapis, odczyt, zmiana uprawnień) bez możliwości uruchamiania komend. Istnieje możliwość innego ustawienia ścieżki chrootowania i dzięki temu również izolacji kont użytkowników SFTP między sobą, ale to odebrałoby możliwość udostępniania swoich plików (w swoim katalogu przez zmianę uprawnień) innym użytkownikom. Użytkownicy będą mogli edytować również listę swoich kluczy publicznych. Można by tę możliwość uniemożliwić umiejscawiając te pliki poza chrootem i/lub nadająć odpowiednie uprawnienia i flagi na pliku. Poza nimi do serwera będzie mógł się zalogować klient _ssh_default też autoryzując się przez klucz, ale nie posiadająć uprawnień do modyfikacji i zapisu plików, katalogów. Użytkownicy Andrzej i Magda również będą widzieć zawartość katalogu użytkownika _ssh_default. Poradnik skupia się na części serwerowej. Serwer będzie uruchomiony na adresie pętli lokalnej 127.0.0.1, więc trzeba go zmienić, jeśli się chce go udostępnić w sieci lokalnej lub Internecie.
Jak zwiększyć swoją wiedzę korzystając z tego poradnika
Osobom chcącym z niego skorzystać proponuję poczytać w manual-u co oznaczają poszczególne polecenia i parametry podane do nich, gdyż większości nie opisałem. Manual można znaleźć korzystając z polecenia man lub czytać online w przeglądarce. Druga opcja jest szczególnie przydatna osobom nie posiadającym zainstalowanego systemu OpenBSD. Osoby korzystające z Gnu/Linuksa (np Debiana) powinny niestety porównać znaczenie opcji w manualu zarówno systemu OpenBSD jak i np Debiana. Obecnie manual OpenBSD znajduje się pod adresem: http://man.openbsd.org/ lub wpisując man w terminalu/konsoli.
Jeśli czytasz manual, a i tak czegoś nie jesteś pewna(y) to oczywiście można zapytać tutaj na forum.
Kilka słów o protokołach FTP, FTPS, SFTP
Protokół FTP służy do przesyłania plików między klientem a serwerem. Powstawał w czasach krystalizowania się stosu TCP/IP i wymaga archaicznych rozwiązań m.in. otwierania dwóch połączeń TCP między klientem a serwerem. Zdefiniowane są dwa tryby, z czego jeden wymaga otwarcia w kliencie portu na firewallu, a drugi wymaga otwarcia szeregu portów na serwerze. Mocno utrudniają one tworzenie sensownej polityki firewalla. FTP sam w sobie nie zapewnia bezpieczeństwa tj szyfrowania, autoryzacji z użyciem kryptografi. W późniejszym czasie stworzono rozszerzenie protokołu FTP w postaci FTPS, które dodaje szyfrowanie i autoryzację, ale dalej nie jest to najlepsze rozwiązanie. Dodatkowo szyfrowanie utrudnia możliwość dynamicznego otwierania portów na firewallu, co było jednym z rozwiązań wcześniej wspomnianych problemów z trybami i połączeniami TCP.
Na szczęście istnieje protokół SFTP. Jest to protokół z punktu widzenia osoby używającej klienta podobny do FTP, lecz działający z użyciem jednego, stałego portu i od początku projektowany jako bezpieczny (m.in. tunelowany w bezpiecznym połączeniu np protokołu SSH).
Zabezpieczenia
Zabezpieczenie danych między kontami na serwerze opiera się na tradycyjnych Uniksowych uprawnieniach do plików. Użytkownicy powinni więc sami uważać z jakimi uprawnieniami tworzą pliki. Procesy użytkowników będą zchrootowane, co w połączeniu ze zrzucaniem uprawnień przez proces powinno ochronić przed dostępem do reszty drzewa katalogów. Komenda sftp jest wymuszana w konfiguracji, co oznacza odebranie prawa do innych komend. Innymi słowy nie można korzystać z shella. Niestety nie jest ograniczony rozmiar plików i całkowita objętość wszystkich plików. Najbezpieczniej byłoby podmontować /mnt/chroots/ jako oddzielny system plików i dodać dodatkową ochronę przed złośliwym zapełnieniem za pomocą quota'y i ograniczenia maksymalnego rozmiaru pliku. Jeśli jednak założymy, że użytkownicy są w miarę zaufani i nie będą próbować szkodzić serwerowi (np znajomi albo to osobisty serwer) to serwer jest całkiem bezpieczny. Dane użytkownika będą dosyć bezpieczne jeśli będzie chronił swój klucz prywatny i nie nadawał na swoich plikach zbyt luźnych uprawnień. Oprócz tego przydałby się proaktywny firewall potrafiący zablokować hosty po IP w czasie prób skanowania portów i wielokrotnych połączeniach w krótkim czasie do serwera OpenSSH. Możnaby pokusić się również o zwiększenie logowanych informacji o działaniach użytkowników.
Last but not least: Oczywiście dalej ważne jest w odpowiednio krótkim czasie instalowanie zaaktualizowanej wersji oprogramowania, by łatać publicznie znane dziury.
OpenBSD a wydajność dostępu (odczyt, zapis) do dużych ilości danych w postaci plików
Złożone projekty, które są dostępne na rynku, zwykle mają zarówno mocne jak i słabe strony. Tak też jest z OpenBSD. Niestety system plików (FFS) jak i podsystem pamięci masowej w systemie OpenBSD jest relatywnie słabą stroną systemu. System plików jest dosyć prymitywny. W innych systemach operacyjnych pamięć podręczna systemu operacyjnego potrafi dosyć wydatnie zwiększyć wydajność odczytu i zapisu na dysk, a w OpenBSD nie jest to zbyt skuteczne. Plusem dla tej części systemu operacyjnego to stabilność systemu plików. Istnieje też możliwość skorzystania z programowego RAID-a wbudowanego w OpenBSD. W przypadku prostego serwera dla siebie i znajomych ograniczenia nie powinny dać się we znaki, ale w przypadku tworzenia bardziej obciążanego (pod względem ilości danych, rządań zapisu i odczytu) serwera warto zastanowić się nad wyborem innego systemu operacyjnego np FreeBSD z systemem plików ZFS.
Niestety nie wszystkie zabezpieczenia przed włamaniami, wbudowane w OpenSSH (mam namyśli separację procesów, zadań i przywilejów - z ang. Privilege separation), nie zawsze na innych systemach operacyjnych działają tak poprawnie jak w systemie OpenBSD.
Do dzieła
Dane będą przechowywane w podkatalogach /mnt/chroots/sftp/home/. Zakładam, że mogę zmieniać uprawnienia /chroots, bo tam jeszcze nie ma innych podkatalogów.
mkdir -p /mnt/chroots/sftp/home/
Tworzymy grupę zbiorczą dla wszystkich użytkowników logujących się do sftp:
groupadd _ssh_wszyscy
Nadajemy uprawniania:
chown root:wheel /mnt/chroots
# R oznacza nadanie uprawnień wszystkim podfolderom i plikom w nich. P oznacza nie podążanie za żadnym symlinkami.
chown -RP root:_ssh_wszyscy /mnt/chroots/sftp/
chmod -RP 640 /mnt/chroots
chmod 1600 /mnt/chroots/sftp/
# Na katalogach, i tylko dla nich, nadajemy uprawnienia właścicielowi i grupie, by mogli do nich wchodzić
find /mnt/chroots/ -type d -exec chmod ug+x {} \;
chmod o+x /mnt/chroots
# Odpowiednik Gnu/Linuksowego chattr +a
chflags uappnd /mnt/chroots/sftp
Na początku tworzone są katalogi użytkowników i plik name, który w łatwy sposób pozwoli zorientować się jako kto są zalogowani.
mkdir -p /mnt/chroots/sftp/home/ssh_andrzej
mkdir -p /mnt/chroots/sftp/home/ssh_magda
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro
echo "Andrzej" > /mnt/chroots/sftp/home/ssh_andrzej/name
echo "Magda" > /mnt/chroots/sftp/home/ssh_magda/name
echo "Domyślny"> /mnt/chroots/sftp/home/ssh_shared_ro/name
Oprócz tego można też wrzucić plik fałszywej powłoki wewnątrz chroota
mkdir -p /mnt/chroots/sftp/bin
ln -s /bin/date /mnt/chroots/sftp/bin/date
chown -RP root:wheel /mnt/chroots/sftp/bin/
chmod a+x /mnt/chroots/sftp/bin/
chmod 511 /mnt/chroots/sftp/bin/date
Tworzymy konta użytkowników, ustawiamy fake'owego shella, dodajemy użytkowników do zbiorczej grupy _ssh_wszyscy:
useradd -d /mnt/chroots/sftp/home/ssh_shared_ro -G _ssh_wszyscy -e 0 -s /bin/date _ssh_default
useradd -d /mnt/chroots/sftp/home/ssh_andrzej -G _ssh_wszyscy -e 0 -s /bin/date _ssh_andrzej
useradd -d /mnt/chroots/sftp/home/ssh_magda -G _ssh_wszyscy -e 0 -s /bin/date _ssh_magda
Nadajemy uprawnienia katalogom:
chown -RP root:_ssh_wszyscy /mnt/chroots/sftp/home/ssh_shared_ro
chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej
chown -RP _ssh_magda:_ssh_magda /mnt/chroots/sftp/home/ssh_magda
chmod -RP 600 /mnt/chroots/sftp/home/ssh_andrzej
chmod -RP 600 /mnt/chroots/sftp/home/ssh_magda
chmod -RP 440 /mnt/chroots/sftp/home/ssh_shared_ro
find /mnt/chroots/sftp/home -type d -exec chmod ug+x {} \;
chmod +t /mnt/chroots/sftp/home/ssh_shared_ro
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/name
chmod +t /mnt/chroots/sftp/home
chflags uappnd /mnt/chroots/sftp/home/
Tworzenie kluczy dla hosta W tym celu tworzymy tymczasowy katalog. Warto pamiętać, że /tmp jest zwykle czyszczone podczas restartu.
mkdir -p /tmp/klucze_ssh
chown -RP root /tmp/klucze_ssh
chmod -RP 600 /tmp/klucze_ssh
cd /tmp/klucze_ssh
Właściwa część tworzenia kluczy. Dla hosta zawsze bez hasła
ssh-keygen -f ssh_host_ed25519_key -o -t ed25519
ssh-keygen -b 3072 -f ssh_host_rsa_key -o -t rsa
Klucze należy przenieść do miejsca, w którym będzie ich szukał serwer OpenSSH. Skopiowanie i nadanie uprawnień.
cp ssh_host_*[key,pub] /etc/ssh/
chown root:wheel /etc/ssh/ssh_host_*[key,pub]
chmod 600 /etc/ssh/ssh_host_*[key,pub]
Tworzenie kluczy dla użytkowników Dla uproszczenia też stworzyłem bez hasła
ssh-keygen -C andrzej -f ssh_id_andrzej_ed25519_key -o -t ed25519
ssh-keygen -C andrzej -b 3072 -f ssh_id_andrzej_rsa_key -o -t rsa
ssh-keygen -C magda -f ssh_id_magda_ed25519_key -o -t ed25519
ssh-keygen -C magda -b 3072 -f ssh_id_magda_rsa_key -o -t rsa
ssh-keygen -C default -f ssh_id_default_ed25519_key -o -t ed25519
ssh-keygen -C default -b 3072 -f ssh_id_default_rsa_key -o -t rsa
Stworzone zostały klucze publiczne i prywatne w typach rsa i ed25519. Daje to 4 pliki na użytkownika. Po podanych komendach stworzone zostanie łącznie 12 plików.
Pliki z końcówką .pub to pliki publiczne. Należy je wrzucić do podkatalogu ~/.ssh/authorized_keys2 w katalogach domowych użytkowników na serwerze.
mkdir -p /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_magda/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/
Dopisujemy klucze
Restrict wyłącza forwardowanie itp, ale opcje w sshd_config mają pierszeństwo. Poza tym użytkownicy Andrzej i Magda mogą zmieniać własne pliki, również authorized_keys2, więc mogą usunąć restrict.
awk '{printf "restrict ";print $0}' ssh_id_andrzej_*pub > /mnt/chroots/sftp/home/ssh_andrzej/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_magda_*pub > /mnt/chroots/sftp/home/ssh_magda/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_default_*_key.pub > /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/authorized_keys2
Zmieniamy uprawnienia:
chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej/.ssh/
chown -RP _ssh_magda:_ssh_magda /mnt/chroots/sftp/home/ssh_magda/.ssh/
chown -RP _ssh_default:_ssh_default /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chmod 600 /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/authorized_keys2
chmod 600 /mnt/chroots/sftp/home/ssh_magda/\.ssh/authorized_keys2
chmod 400 /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
chmod 700 /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
chmod 700 /mnt/chroots/sftp/home/ssh_magda/\.ssh/
chmod 1500 /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_magda/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_andrzej/.ssh/
Możemy przenieść klucze prywatne do klienta
Pliki bez końcówki pub (czyli kończące się na key) to klucze prywatne. Należy je w bezpieczny sposób przenieść na klienta do podkatalogu ~/.ssh/ w katalogu domowym użytkownika do plików id_rsa i id_ed25519.
Zakładając, że testujemy i mamy klienta na tym samym komputerze co serwer, testowy klient ma być uruchomiony na koncie użytkownika test i chcemy mięć dostęp do serwera z poziomu użytkownika default, plik klucza prywatnego typu ed25519 przeniesiemy poleceniami:
cp ssh_id_default_ed25519_key /home/test/.ssh/id_ed25519
chown test:test /home/test/.ssh/id_ed25519
chmod 600 /home/test/.ssh/id_ed25519
Podobnie z kluczami publicznymi:
cp ssh_id_default_ed25519_key.pub /home/test/.ssh/id_ed25519.pub
chown test:test /home/test/.ssh/id_ed25519.pub
chmod 600 /home/test/.ssh/id_ed25519.pub
Przenieśliśmy klucze typu ed25519. Analogicznie przenosimy klucze RSA.
Zawartość wklejana do pliku konfiguracji
Główny plik konfiguracji ma domyślną ścieżkę /etc/ssh/sshd_config. Jego zmiana jednak na nasz spowoduje uruchomienie tylko i wyłącznie SFTP, czyli nie można będzie zalogować się i wydawać komend! Jeśli masz zdalny serwer prawdopodobnie chcesz stworzyć inną usługę sshd i wgrać konfigurację dla niej pod inną ścieżką (by nie utracić zdalnego dostępu do serwera), ale w tym poradniku dla uproszczenia ustawiam go jako /etc/ssh/sshd_config.
ListenAddress 127.0.0.1
AllowGroups _ssh_wszyscy
#
ChallengeResponseAuthentication no
ClientAliveCountMax 1
ClientAliveInterval 15
Compression yes
Ciphers chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-rsa
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAcceptedKeyTypes ssh-ed25519,ssh-rsa
IPQoS throughput
KbdInteractiveAuthentication no
PasswordAuthentication no
LoginGraceTime 10
MaxAuthTries 2
MaxSessions 3
MaxStartups 2
PermitTunnel no
PermitUserEnvironment no
PermitUserRC no
X11Forwarding no
StrictModes yes
AuthorizedKeysFile "%h/.ssh/authorized_keys2"
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
AllowAgentForwarding no
AllowTcpForwarding no
AllowStreamLocalForwarding no
PermitTTY no
PermitRootLogin no
UsePrivilegeSeparation sandbox
Subsystem sftp internal-sftp
ChrootDirectory /mnt/chroots/sftp/
ForceCommand internal-sftp -R -d /home/ssh_shared_ro
Match User _ssh_andrzej
ForceCommand internal-sftp -d /home/ssh_andrzej -u 007
Match User _ssh_magda
ForceCommand internal-sftp -d /home/ssh_magda -u 007
Po tym można zrestartować sshd:
rcctl -f restart sshd
I sprawdzić jego stan:
rcctl check sshd
Połączenie klienta do serwera SFTP
Aby użytkownik test na komputerze kliencie mógł uwierzytalnić się jako inny użytkownik, z użyciem kluczy prywatnych z jego podkatalogu ~/.ssh/, należy użyć komendy:
sftp -i /home/test/.ssh/id_ed25519 _ssh_default@127.0.0.1